#include "HY1C_out.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <libgen.h>
#include "l12_proto.h"
#include "lonlat2pixline.h"
#include "l1_struc.h"
#include "l1_struc.h"
#include "l12_parms.h"

#include "HY1C_OCT_ATMOCOR.h"

int msl12_usage(char *prog);
void write_file(char *dir,float *data,int length,int num){
    if(access(dir,0)==-1)//access函数是查看文件是不是存在
    {
        if (mkdir(dir,0777))//如果不存在就用mkdir函数来创建
        {
            HY1C_out("creat file bag failed!!!");
        }
    }
    char filename[256];
    sprintf(filename,"%s%s%d%s",dir,"/data_",num,".txt");
    FILE * fp;
    fp = fopen (filename, "w+");
    int i=0;
    for(i=0;i<length;i++){
        fHY1C_out(fp,"%f\t",data[i]);
    }
    fclose(fp);
}

//added by zzq
float **alloc2d_float_added(int w, int h) {
    int   i;
    float **p;
    p = (float **)malloc(h * sizeof(float *));
    if (p == NULL) {
        fHY1C_out(stderr, "-E- %s line %d: Memory allocation failed.\n",
            __FILE__, __LINE__);
        return(p);
    }

    p[0] = (float *)malloc(w * h * sizeof(float));
    if (p[0] == NULL) {
        fHY1C_out(stderr, "-E- %s line %d: Memory allocation failed.\n",
            __FILE__, __LINE__);
        free(p);
        return(NULL);
    }

    for (i = 1; i < h; i++) {
        p[i] = &(p[0][i*w]);
    }

    return(p);
}

float ***alloc3d_float_added(int w, int h,int ib) {
    float ***three_point;
    int i,j,k;
    three_point=(float ***)malloc(ib*sizeof(float **));
    for(i=0;i<2;i++){
        three_point[i]=(float **)malloc(h*sizeof(float *));
        for(j=0;j<3;j++){
            three_point[i][j]=(float *)malloc(w*sizeof(float));
            for(k=0;k<4;k++){
                three_point[i][j][k]=BAD_FLT;
            }
        }
    }
    return three_point;
}

l1rec_HY1C *read_Lt_H1C(char *filename) {
    l1rec_HY1C *l1recHY1C;
    l1recHY1C=(l1rec_HY1C *) malloc(sizeof(l1rec_HY1C));

    int32 sd_id;

    int32 sds_id;
    int32 status=0;

    int32 rank;
    int32 nt;
    int32 nattrs;
    int32 start[2] = {0,0};
    int32 edges[2] = {0,0};
    char  name[H4_MAX_NC_NAME] = "";
    char  sdsname[H4_MAX_NC_NAME] = "";
    char *file =filename;
    sd_id = SDstart(file, DFACC_RDONLY);
    if (sd_id == -1) {
        HY1C_out("-E- %s:  Error opening file %s.\n",
            __FILE__, file);
        exit(1);
    }

//    int datestr;
    char yearstr[5] = "20";
    char tmp_str[56]="demodemo";
    char year_tmps[56]={'0'}, doystr[56]={'0'};
    char year[56]={'0'};

    int32  npix;
    int32  nscan;

    status = SDreadattr(sd_id, SDfindattr(sd_id, "Number of Scan Lines"),&nscan);
    status = SDreadattr(sd_id, SDfindattr(sd_id,"Pixels Per Scan Line"), &npix);
    status = SDreadattr(sd_id, SDfindattr(sd_id, "Range Ending Date"), &tmp_str);
    strncpy(doystr,tmp_str+9,3);
    strncpy(year,tmp_str+0,4);


     int year_int = atoi(year);
     int day = atoi(doystr);


    int32  dims[2];
    int32  type;
    int32  numattr;
    /* Get pixel and scan dimensions */
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, ("L_412")));
    if (SDgetinfo(sds_id, NULL, &rank, dims, &type, &numattr) == -1) {
        fHY1C_out(stderr, "-E- %s line %d: error getting dimension info.\n",
            __FILE__, __LINE__);
//		return(HDF_FUNCTION_ERROR);
    }

    npix = dims[1];
    nscan = dims[0];

    l1recHY1C->npix = npix;
    l1recHY1C->nscans = nscan;

    float **Lt_tmp = alloc2d_float_added(npix, nscan);

    int32 status_getvar;
    char var_list[8][4] = { {"412"},{"443"},{"490"},{"520"},{"565"},{"670"},{"750"},{"865"}};
    char varname[FILENAME_MAX] = " ";

    float **Lt[8] = {alloc2d_float_added(npix, nscan),alloc2d_float_added(npix, nscan),alloc2d_float_added(npix, nscan),alloc2d_float_added(npix, nscan),
        alloc2d_float_added(npix, nscan) ,alloc2d_float_added(npix, nscan) ,alloc2d_float_added(npix, nscan) ,alloc2d_float_added(npix, nscan)};
    float ***Lt_zzq;
    Lt_zzq=(float ***)malloc(sizeof (float **)*8);
    int tmp_i=0,tmp_j=0,tmp_k=0;
    for(tmp_i=0;tmp_i<8;tmp_i++){
        Lt_zzq[tmp_i]=(float **)malloc(sizeof (float *)*nscan);
        for(tmp_j=0;tmp_j<nscan;tmp_j++){
            Lt_zzq[tmp_i][tmp_j]=(float *)malloc(sizeof(float)*npix);
        }
    }


//    float ***Lt_trans;
//    Lt_trans=(float ***)malloc(sizeof (float **)*nscan);
//    for(tmp_i=0;tmp_i<nscan;tmp_i++){
//        Lt_trans[tmp_i]=(float **)malloc(sizeof (float *)*npix);
//        for(tmp_j=0;tmp_j<npix;tmp_j++){
//            Lt_trans[tmp_i][tmp_j]=(float *)malloc(sizeof(float)*8);
//        }
//    }





    int ilt = 0;

    for (ilt = 0; ilt < 8; ilt++) {
        Lt_tmp = NULL;
        Lt_tmp = alloc2d_float_added(npix, nscan);
        strcpy(varname, "L_");
        char tmp_val_char[4];
        tmp_val_char[0]=var_list[ilt][0];
        tmp_val_char[1]=var_list[ilt][1];
        tmp_val_char[2]=var_list[ilt][2];
        tmp_val_char[3]='\0';
        strcat(varname, tmp_val_char);
        HY1C_out("Loading Lt from %s in %s\n", varname, file);

        //static float L_412[][];

        strcpy(sdsname, varname);
        sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
        status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
        status = SDreaddata(sds_id, start, NULL, dims, (VOIDP)Lt_tmp[0]);
        if (status != 0) {
            HY1C_out("-E- %s:  Error reading SDS %s from %s.\n", __FILE__, sdsname, file);
            SDend(sd_id);
            //exit(1);
        }

        Lt[ilt] = Lt_tmp;
        Lt_zzq[ilt]=Lt_tmp;
    }
    status = SDendaccess(sds_id);


    //////
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, ("Longitude")));
    if (SDgetinfo(sds_id, NULL, &rank, dims, &type, &numattr) == -1) {
        fHY1C_out(stderr, "-E- %s line %d: error getting dimension info.\n",
            __FILE__, __LINE__);
        //		return(HDF_FUNCTION_ERROR);
    }
    long npix2 = dims[1];
    long nscan2 = dims[0];



    float ** Lon = alloc2d_float_added(npix2, nscan2);

    strcpy(sdsname, "Longitude");
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
    status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
    status = SDreaddata(sds_id, start, NULL, dims, (VOIDP)Lon[0]);
    if (status != 0) {
        HY1C_out("-E- %s:  Error reading SDS %s from %s.\n", __FILE__, sdsname, file);
        SDend(sd_id);
        exit(1);
    }
    else {
        status = SDendaccess(sds_id);
    }

    float ** Lat = alloc2d_float_added(npix2, nscan2);
    strcpy(sdsname, "Latitude");
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
    status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
    status = SDreaddata(sds_id, start, NULL, dims, (VOIDP)Lat[0]);
    if (status != 0) {
        HY1C_out("-E- %s:  Error reading SDS %s from %s.\n", __FILE__, sdsname, file);
        SDend(sd_id);
        exit(1);
    }
    else {
        status = SDendaccess(sds_id);
    }

    float ** solz = alloc2d_float_added(npix2, nscan2);
    strcpy(sdsname, "Solar Zenith Angle");
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
    status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
    status = SDreaddata(sds_id, start, NULL, dims, (VOIDP)solz[0]);
    if (status != 0) {
        HY1C_out("-E- %s:  Error reading SDS %s from %s.\n", __FILE__, sdsname, file);
        SDend(sd_id);
        exit(1);
    }
    else {
        status = SDendaccess(sds_id);
    }
    float ** sola = alloc2d_float_added(npix2, nscan2);
    strcpy(sdsname, "Solar Azimuth Angle");
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
    status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
    status = SDreaddata(sds_id, start, NULL, dims, (VOIDP)sola[0]);
    if (status != 0) {
        HY1C_out("-E- %s:  Error reading SDS %s from %s.\n", __FILE__, sdsname, file);
        SDend(sd_id);
        exit(1);
    }
    else {
        status = SDendaccess(sds_id);
    }

    float ** senz = alloc2d_float_added(npix2, nscan2);
    strcpy(sdsname, "Satellite Zenith Angle");
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
    status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
    status = SDreaddata(sds_id, start, NULL, dims, (VOIDP)senz[0]);
    if (status != 0) {
        HY1C_out("-E- %s:  Error reading SDS %s from %s.\n", __FILE__, sdsname, file);
        SDend(sd_id);
        exit(1);
    }
    else {
        status = SDendaccess(sds_id);
    }

    float ** sena = alloc2d_float_added(npix2, nscan2);
    strcpy(sdsname, "Satellite Azimuth Angle");
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
    status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
    status = SDreaddata(sds_id, start, NULL, dims, (VOIDP)sena[0]);
    if (status != 0) {
        HY1C_out("-E- %s:  Error reading SDS %s from %s.\n", __FILE__, sdsname, file);
        SDend(sd_id);
        exit(1);
    }
    else {
        status = SDendaccess(sds_id);
    }


    int32_t * msec = (int32_t *) malloc(npix*nscan *sizeof(int32_t));

    strcpy(sdsname, "Millisecond");
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, sdsname));
    status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs);
    status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) msec );
    if (status != 0) {
        HY1C_out("-E- %s:  Error reading SDS %s from %s.\n", __FILE__, sdsname, file);
        SDend(sd_id);
        exit(1);
    }
    else {
        status = SDendaccess(sds_id);
    }
    float *tmp_trans;
    tmp_trans=(float *)malloc(sizeof (float)*8*npix*nscan);
    for(tmp_i=0;tmp_i<nscan;tmp_i++){
        for(tmp_j=0;tmp_j<npix;tmp_j++){
            for(tmp_k=0;tmp_k<8;tmp_k++){
                tmp_trans[tmp_i*npix*8+tmp_j*8+tmp_k]=Lt_zzq[tmp_k][tmp_i][tmp_j];
                // tmp_trans[tmp_k*npix*nscan+tmp_i*nscan+tmp_j] = Lt_zzq[tmp_k][tmp_i][tmp_j];
            }
        }
    }
//    float check=Lt_trans[1][0][2];
    int32_t *year_point=(int32_t *)malloc(sizeof (int32_t));
    int32_t *day_point=(int32_t *)malloc(sizeof (int32_t));
    *year_point=year_int;
    *day_point=day;

    float ** reshape_lat = alloc2d_float_added(npix, nscan);
    float ** reshape_lon = alloc2d_float_added(npix, nscan);
    float ** reshape_solz = alloc2d_float_added(npix, nscan);
    float ** reshape_sola = alloc2d_float_added(npix, nscan);
    float ** reshape_senz = alloc2d_float_added(npix, nscan);
    float ** reshape_sena = alloc2d_float_added(npix, nscan);
    int c=0,d=0;
    for(c=0;c<nscan;c++){
        for(d=0;d<npix;d++){
            if(d<npix2){
                reshape_lat[c][d]=Lat[c][d];
                reshape_lon[c][d]=Lon[c][d];
                reshape_solz[c][d]=solz[c][d];
                reshape_sola[c][d]=sola[c][d];
                reshape_senz[c][d]=senz[c][d];
                reshape_sena[c][d]=sena[c][d];
            }else{
                reshape_lat[c][d]=0;
                reshape_lon[c][d]=0;
                reshape_solz[c][d]=0;
                reshape_sola[c][d]=0;
                reshape_senz[c][d]=0;
                reshape_sena[c][d]=0;
            }
        }
    }

    l1recHY1C->npix2 = npix2;
    l1recHY1C->nscans2 = nscan2;
    l1recHY1C->Lt = tmp_trans;
    l1recHY1C->year = year_point;
    l1recHY1C->day = day_point;
    l1recHY1C->msec = msec;
    l1recHY1C->lat = reshape_lat[0];
    l1recHY1C->lon = reshape_lon[0];
    l1recHY1C->solz=reshape_solz[0];
    l1recHY1C->senz=reshape_senz[0];
    l1recHY1C->sola=reshape_sola[0];
    l1recHY1C->sena=reshape_sena[0];
    status = SDend(sd_id);
    return l1recHY1C;
}




//added by zzq

int g_modis_npix = 0;
int g_modis_nscan = 0;


/* -------------------------------------------------------------------- */
/*                            main                                      */
/* -------------------------------------------------------------------- */
int HY1C_OCT_ATMOCOR(const char* inputfile, const char* outfile)
{
    int argc=10;
    char *argv[10];
//    argv=(char **)malloc(sizeof (char *)*10);
    char *param1="HY1C_OCT";
    // char *param2="ifile=/home/oceanoptics/Desktop/MYD021KM.A2015022.1030.006.2015023155921.hdf";
    char param2[256];
    char *param3="l2prod=nLw_412 nLw_443 nLw_490 nLw_520 nLw_565 nLw_670 nLw_750 nLw_865 Rrs_412 Rrs_443 Rrs_490 Rrs_520 Rrs_565 Rrs_670 Rrs_750 Rrs_865 Lt_412 Lt_443 Lt_490 Lt_520 Lt_565 Lt_670 Lt_750 Lt_865 La_412 La_443 La_490 La_520 La_565 La_670 La_750 La_865 Lr_412 Lr_443 Lr_490 Lr_520 Lr_565 Lr_670 Lr_750 Lr_865 epsilon glint_coef aot_865 solz sola senz sena";
    char *param4="geofile=MYD03.A2015022.1030.006.2015023154125.hdf";
    // char param5="ofile=/home/oceanoptics/Desktop/test2.L2";
    char param5[256];
    char *param6="albedo=0.027";
    char *param7="cloud_wave=865";
    char *param8="aer_opt=-2";
    char *param9="aer_swir_long=865";
    char *param10="aer_swir_short=748";
    int32_t   iscan    = 0;          /* input scan number                  */
    int32_t   oscan    = 0;          /* output scan number                 */
    int32_t   npix     = 0;          /* input number pixels per scan       */
    int32_t   spix     = 0;          /* start pixel for subscene process   */
    int32_t   epix     = -1;         /* end pixel for subscene process     */
    int32_t   dpix     = 1;          /* pixel increment for sub-sampling   */
    int32_t   sscan    = 0;          /* start scan for subscene process    */
    int32_t   escan    = -1;         /* end scan for subscene process      */
    int32_t   dscan    = 1;          /* scan subsampling increment         */

    l1str   *l1rec;                /* generic level-1b scan structure    */
    l2str   *l2rec;                /* generic level-2  scan structure    */
    tgstr   *tgrec;                /* structure to store target values   */
    aestr   *aerec;                /* structure to store aerosol values  */
    instr   *input;                /* input parameters structure         */
    l1str *data_hic;
    l1rec_HY1C *read_hic;
    filehandle l1file;            /* input l1 file handle               */
    filehandle tgfile;            /* input target file handle           */
    filehandle aefile;            /* input aerosol file handle          */
    filehandle ofile[MAX_OFILES]; /* output file handles                */

    double start_time;
    int    num_ofiles = 0;
    int32_t   i;

    argv[0]=param1;
    sprintf(param2, "ifile=%s", inputfile);
    argv[1]=param2;
    argv[2]=param3;
    argv[3]=param4;
    sprintf(param5, "ofile=%s", outfile);
    argv[4]=param5;
    argv[5]=param6;
    argv[6]=param7;
    argv[7]=param8;
    argv[8]=param9;
    argv[9]=param10;

    if (argc == 1)
    {
      l2gen_usage("l2gen");
      return -1;
    }

    // see if help on command line
    for(i=0; i<argc; i++) {
        if((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-help") == 0)) {
            l2gen_usage("l2gen");
            return 1;
        }
    }

    setvbuf(stdout, NULL, _IOLBF, 0);
    setvbuf(stderr, NULL, _IOLBF, 0);

    // allocate structures
    l1rec = (l1str*) malloc(sizeof(l1str));
    l2rec = (l2str*) malloc(sizeof(l2str));
    tgrec = (tgstr*) malloc(sizeof(tgstr));
    aerec = (aestr*) malloc(sizeof(aestr));
    input = (instr*) malloc(sizeof(instr));
    data_hic=(l1str *)malloc(sizeof (l1str));
    read_hic=(l1rec_HY1C *)malloc(sizeof (l1rec_HY1C));
    if(!l1rec || !l2rec || !tgrec || !aerec || !input || !data_hic || !read_hic) {
        HY1C_out("-E- %s %d: Error allocating data structures.\n",__FILE__, __LINE__);
        exit(FATAL_ERROR);
    }
    //data init
    /* Initialize file handles */
    filehandle_init(&l1file);
    filehandle_init(&tgfile);
    filehandle_init(&aefile);
    for (i=0; i<MAX_OFILES; i++)
        filehandle_init(&ofile[i]);
    msl12_input_init(input);
    /* Parse input parameters */
    if (msl12_input(argc, argv, "l2gen", input, &l1file) != 0) {
        HY1C_out("-E- %s: Error parsing input parameters.\n",argv[0]);
        exit(FATAL_ERROR);
    }
    if (access(input->ifile[0], F_OK) || access(input->ifile[0], R_OK)) {
        HY1C_out("-E- %s: Input file '%s' does not exist or cannot open.\n",
               argv[0], input->ifile[0]);
        exit(FATAL_ERROR);
    }
    /* if north, south, east, and west used, convert to pix and line */
    if(input->north != -999 || input->south != -999
            || input->east != -999 || input->west != -999
            || input->xbox != -1 || input->ybox != -1) {

        int result;
        int save_verbose = want_verbose;

        // turn off the extra output
        want_verbose = 0;
        if(input->north != -999 && input->south != -999
                && input->east != -999 && input->west != -999
                && input->xbox == -1 && input->ybox == -1) {

            // north, south, east and west are set
            result = lonlat2pixline1(input->ifile[0], input->geofile,
                input->resolution, input->west, input->south, input->east, input->north,
                &input->spixl, &input->epixl, &input->sline, &input->eline);

        } else if(input->north == -999 && input->south != -999
                && input->east == -999 && input->west != -999
                && input->xbox != -1 && input->ybox != -1) {

            // south, west, xbox, ybox are set
            result = lonlat2pixline2(input->ifile[0], input->geofile,
                input->resolution, input->west, input->south, input->xbox, input->ybox,
                &input->spixl, &input->epixl, &input->sline, &input->eline);

        } else {
            HY1C_out("-E- %s: set either \n", argv[0]);
            HY1C_out("    1) north, south, east and west or\n");
            HY1C_out("    2) south, west, xbox, ybox\n");
            exit(FATAL_ERROR);
        }
        want_verbose = save_verbose;

        if(result==120) { // requested box includes the whole file
            input->spixl = 1;
            input->epixl = -1;
            input->sline = 1;
            input->eline = -1;
        } else {
            if(result!=0 && result!=110) {
                HY1C_out("-E- %s: north, south, east, west box not in this file.\n", argv[0]);
                exit(LONLAT_ERROR);
            }
        }
    }

    /*									*/
    /* Determine number of output files.   	                        */
    /*									*/
    for (i=0, num_ofiles=0; i<MAX_OFILES; i++, num_ofiles++)//MAX_OFILES=10
      if (input->ofile[i][0] == '\0')
        break;

    if (num_ofiles == 0) {
        HY1C_out("-E- %s: No output file name given\n", argv[0]);
        exit(FATAL_ERROR);
    }

    /*									*/
    /* Open input file and get sensor and scan information from handle. */
    /*									*/
    if (openl1(&l1file) != 0) {
        HY1C_out("-E- %s: Error opening %s for reading.\n",
            argv[0],l1file.name);
        exit(FATAL_ERROR);
    }
    //init l1 file finished
    npix = l1file.npix;

    // Open aerosol file if provided

    if (input->aerfile[0] != '\0') {
        aerec->mode = ON;
        strcpy(aefile.name, input->aerfile);
        if (open_aer(&aefile) != 0) {
            HY1C_out("-E- %s: Error opening %s for reading.\n",
                argv[0],aefile.name);
            exit(FATAL_ERROR);
        }
        if (aefile.npix != npix) {
            HY1C_out("-E- %s: Incompatible scan length between %s and %s: %d, %d.\n",
                argv[0],l1file.name,aefile.name,aefile.npix,npix);
            exit(FATAL_ERROR);
        }
    } else
        aerec->mode = OFF;

    // Open calibration target file if provided

    if (input->tgtfile[0] != '\0') {
        tgrec->mode = ON;
        strcpy(tgfile.name, input->tgtfile);
        HY1C_out("Opening carious calibration target file: %s\n",tgfile.name);
        if (open_target(&tgfile) != 0) {
            HY1C_out("-E- %s: Error opening %s for reading.\n",
                argv[0],tgfile.name);
            exit(FATAL_ERROR);
        }
        if (tgfile.npix != npix) {
            HY1C_out("-E- %s: Incompatible scan length between %s and %s.\n",
                argv[0],l1file.name,tgfile.name);
            exit(FATAL_ERROR);
        }
        l2rec->tgrec = tgrec;
    } else {
        tgrec->mode = OFF;
        l2rec->tgrec = NULL;
    }

    /*									*/
    /* Allocate memory for L1 and L2 scan data and opional input recs	*/
    /*									*/
  //char*filename="/home/oceanoptics/test_l2gen/H1BCLR120616015227037.L1B.HDF";
    char*filename="H1BCLR130612005432195.L1B.HDF";
    int32 sd_id;
    int32 sds_id;
    int32 rank;
    int32    dims[2];
    int32  type;
    int32  numattr;
    int32 nscan,nscan2,npix2;
    sd_id = SDstart(filename, DFACC_RDONLY);
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, ("L_412")));
    SDgetinfo(sds_id, NULL, &rank, dims, &type, &numattr);
    nscan=dims[0];npix=dims[1];
    sds_id = SDselect(sd_id, SDnametoindex(sd_id, ("Latitude")));
    SDgetinfo(sds_id, NULL, &rank, dims, &type, &numattr);
    nscan2=dims[0];npix2=dims[1];
    SDendaccess(sds_id);
    SDend(sd_id);

    int flags;
    flags=1;

    if ( alloc_l1(npix,NBANDS,NBANDSIR,l1file.n_inprods,l1rec) == 0 ) {
        HY1C_out("-E- %s: Unable to allocate L1 record.\n",argv[0]);
        exit( FATAL_ERROR );
    }
    /*
    if ( alloc_l1(npix,8,2,l1file.n_inprods,l1rec) == 0 ) {
        HY1C_out("-E- %s: Unable to allocate L1 record.\n",argv[0]);
        exit( FATAL_ERROR );
    }*/

    if ( alloc_l1(npix,8,2,l1file.n_inprods,data_hic) == 0 ) {
        HY1C_out("-E- %s: Unable to allocate L1 record.\n",argv[0]);
        exit( FATAL_ERROR );
    }

    // force to match (npix, 8, 2);according to data_hic 20180822
    l1rec->nbands = 8;
    l1rec->nbandsir = 2;
    l1rec->length = data_hic->length;


    if ( alloc_hic(npix,nscan,8,2,l1file.n_inprods,read_hic) == 0 ) {
        HY1C_out("-E- %s: Unable to allocate HiC record.\n",argv[0]);
        exit( FATAL_ERROR );
    }
    if ( alloc_l2(npix,8,l2rec) == 0 ) {
        HY1C_out("-E- %s: Unable to allocate L2 record.\n",argv[0]);
        exit( FATAL_ERROR );
    }

    read_hic=read_Lt_H1C(filename);
//    float check=read_hic->Lt[1*npix*8];

    if (aerec->mode == ON) {//off
        if ( alloc_aer(npix,NBANDS,aerec) == 0 ) {
            HY1C_out("-E- %s: Unable to allocate aerfile record.\n",argv[0]);
            exit( FATAL_ERROR );
        }
    }
    if (tgrec->mode == ON) {//off
       if (alloc_target(npix,NBANDS,tgrec) == 0) {
            HY1C_out("-E- %s: Unable to allocate target record.\n",argv[0]);
            exit( FATAL_ERROR );
       }
    }
    int modis_npix=l1file.npix;
    int modis_nscan=l1file.nscan;

    input->epixl=read_hic->npix;
    input->eline=read_hic->nscans;
    l1file.npix=read_hic->npix;
    l1file.nscan=read_hic->nscans;
    /* Set the end pixel if it was not set by command argument	        */
    if (input->epixl == -1 || input->epixl > l1file.npix)
        input->epixl = l1file.npix;
    if (input->eline == -1 || input->eline > l1file.nscan)
        input->eline = l1file.nscan;
    if (input->spixl < 1)
        input->spixl = 1;
    if (input->sline < 1)
        input->sline = 1;

    spix  = MAX(input->spixl - 1, 0);
    epix  = MIN(input->epixl - 1, l1file.npix-1);
    dpix  = MAX(input->dpixl,1);
    sscan = MAX(input->sline - 1, 0);
    escan = MIN(input->eline - 1, l1file.nscan-1);
    dscan = MAX(input->dline,1);

    if (sscan > escan || spix > epix) {
        HY1C_out("-E- %s: scan and pixel limits make no sense.\n",argv[0]);
        HY1C_out(" start scan  = %d\n",sscan+1);
        HY1C_out(" end   scan  = %d\n",escan+1);
        HY1C_out(" start pixel = %d\n",spix +1);
        HY1C_out(" end   pixel = %d\n",epix +1);
        exit( FATAL_ERROR );
    }


    /* Note: for the L1 file, npix is still the native scan pixel count */
    l1file.spix = spix;                /* start pixel rel to L1 scan    */
    l1file.epix = epix;                /* end   pixel rel to L1 scan    */
    l1file.dpix = dpix;                /* pix-increment                 */

    /* Make sure number of pixel control points is adequate */
    if (input->ctl_pt_incr > 0)
        if (((epix-spix)/dpix+1)/input->ctl_pt_incr < 25)
            input->ctl_pt_incr = 1;


    /*                                                                  */
    /* Open output file(s)                                              */
    /*                                                                  */
    if (input->mode != FORWARD) {
        /*                                                              */
        /* Transfer sensor and scan info to recal filehandle and open   */
        /*                                                              */
        strcpy(ofile[0].name, input->ofile[0]);
        ofile[0].format      = FMT_L1HDF;
        ofile[0].mode        = WRITE;
        ofile[0].sensorID    = l1file.sensorID;
        ofile[0].nbands      = l1file.nbands;
        ofile[0].nbandsir    = l1file.nbandsir;
        ofile[0].bindx       = l1file.bindx;
        ofile[0].ndets       = l1file.ndets;
        ofile[0].spix        = spix;
        ofile[0].epix        = epix;
        ofile[0].dpix        = dpix;
        ofile[0].npix        = (epix - spix)/dpix + 1;
        ofile[0].length      = l1rec->length;
        ofile[0].nscan       = (escan - sscan)/dscan + 1;
        ofile[0].ctl_pt_incr = input->ctl_pt_incr;
        ofile[0].pro_control = input->pro_control;
        ofile[0].input_parms = input->input_parms;
        ofile[0].input_files = input->input_files;
        ofile[0].calfile     = input->calfile;
        ofile[0].mask_names  = input->mask_names;
        ofile[0].input       = input;

        HY1C_out("Opening L1B output file: %s\n",ofile[0].name);

        if (openl1(&ofile[0]) != 0) {
            HY1C_out("-E- %s: Error opening %s for writing.\n",
                argv[0],ofile[0].name);
            exit(FATAL_ERROR);
        }

    } else {
        /*                                                              */
        /* Transfer sensor and scan info to output filehandles and open */
        /*                                                              */
        HY1C_out("\n");
        for (i=0; i<num_ofiles; i++) {
            strcpy(ofile[i].name, input->ofile[i]);
        if ( strcmp(input->fmtofile[i], "NCDF") == 0) {
          ofile[i].format      = FMT_L2NCDF;
        } else {
          ofile[i].format      = FMT_L2HDF;
        }
            ofile[i].mode        = WRITE;
            ofile[i].sensorID    = l1file.sensorID;
            ofile[i].nbands      = l1file.nbands;
            ofile[i].nbandsir    = l1file.nbandsir;
            ofile[i].bindx       = l1file.bindx;
            ofile[i].ndets       = l1file.ndets;
            ofile[i].spix        = spix;
            ofile[i].epix        = epix;
            ofile[i].dpix        = dpix;
            ofile[i].npix        = (epix - spix)/dpix + 1;
            ofile[i].length      = l2rec->length;
        ofile[i].nscan       = (escan - sscan)/dscan + 1;
            strcpy(ofile[i].l2prod, input->l2prod[i]);
            strcpy(ofile[i].def_l2prod, input->def_l2prod[i]);
            ofile[i].ctl_pt_incr = input->ctl_pt_incr;
            ofile[i].pro_control = input->pro_control;
            ofile[i].input_parms = input->input_parms;
            ofile[i].input_files = input->input_files;
            ofile[i].calfile     = input->calfile;
            ofile[i].mask_names  = input->mask_names;
            ofile[i].input       = input;
        ofile[i].orbit_node_lon     = l1file.orbit_node_lon;
        ofile[i].orbit_number       = l1file.orbit_number;
        strcpy(ofile[i].node_crossing_time, l1file.node_crossing_time);

            HY1C_out("Opening: %s\n",ofile[i].name);
            if (openl2(&ofile[i]) != 0) {
                HY1C_out("-E- %s: Error opening %s for writing.\n",
                    argv[0],ofile[i].name);
                exit(FATAL_ERROR);
            }
        }
        HY1C_out("\n");
    }

    /*								        */
    /* Transfer any additional header info to the record headers	*/
    /*								        */
    l2rec->sensorID  = l1file.sensorID;
    l2rec->nbands    = l1file.nbands;
    l2rec->nbandsir  = l1file.nbandsir;
    l2rec->bindx     = l1file.bindx;
    l2rec->ndets     = l1file.ndets;
    l2rec->input     = input;
    l2rec->nscans    = ofile[i].nscan;

    HY1C_out("\n\nBegin %s Version %s Processing\n",PROGRAM,VERSION);
    HY1C_out("Sensor is %s\n",sensorName[l1file.sensorID]);
    HY1C_out("Sensor ID is %d\n",l1file.sensorID);
    HY1C_out("Sensor has %d reflective bands\n",l1file.nbands );
    HY1C_out("Sensor has %d emmissive bands\n",l1file.nbandsir );
    HY1C_out("Number of along-track detectors per band is %d\n",l1file.ndets );
    HY1C_out("Number of input pixels per scan is %d\n",l1file.npix);
    HY1C_out("Processing pixels %d to %d by %d\n",spix+1,epix+1,dpix);
    HY1C_out("Processing scans %d to %d by %d\n",sscan+1,escan+1,dscan);

    if (input->proc_ocean != 0)
        HY1C_out("Ocean processing enabled\n");
    else
        HY1C_out("Ocean processing disabled\n");

    if (input->proc_land != 0)
        HY1C_out("Land processing enabled\n");
    else
        HY1C_out("Land processing disabled\n");

    if (input->atmocor != 0)
        HY1C_out("Atmospheric correction enabled\n");
    else
        HY1C_out("Atmospheric correction disabled\n");

    if (aerec->mode == ON) {
        HY1C_out("Aerosol parameters will be extracted from %s\n",
            aefile.name);
    }

    if(input->prodXMLfile[0] != '\0') {
        HY1C_out("\nWriting product information to XML file %s\n", input->prodXMLfile);
        write_product_XML_file(input->prodXMLfile);
    }

    start_time = now();
    HY1C_out("\nBegin MSl12 processing at %s\n\n", ydhmsf(start_time,'L'));
    /*								        */
    /* 	Read file scan by scan, convert to L2, and write.		*/
    /*								        */

    //nscan=dims[0];npix=dims[1];
    //l1file.npix=modis_npix;
    //l1file.nscan=modis_nscan;

    g_modis_npix = modis_npix;
    g_modis_nscan = modis_nscan;

    for (iscan=sscan, oscan=0; iscan<=escan; iscan+=dscan, oscan++) {
        // if (oscan >= 10)
        //     break;
        /*                                                              */
        /* This call returns the specified record, but it internally    */
        /* buffers enough records to facilitate L1B filtering.          */
        /*                                                              */
        if (getl1rec(&l1file,input,iscan,data_hic,read_hic,oscan,flags) != 0) {
            exit(FATAL_ERROR);
        }
//        float check1=l1rec->Lr[8*1664-1];
//        float check2=l1rec->tg_sol[1663];
//        float check3=l1rec->tg_sen[1663];
//        float check4=l1rec->t_sen[1663];
//        float check5=l1rec->t_sol[1663];
        //write_file("/home/oceanoptics/debug_file/Lr",data_hic->Lr,data_hic->npix*8,oscan);
        //write_file("/home/oceanoptics/debug_file/tLf",data_hic->tLf,data_hic->npix,oscan);

        //write_file("/home/oceanoptics/debug_file/tg_sol",data_hic->tg_sol,data_hic->npix*8,oscan);
        //write_file("/home/oceanoptics/debug_file/tg_sen",data_hic->tg_sen,data_hic->npix*8,oscan);

        //write_file("/home/oceanoptics/debug_file/t_sol",data_hic->t_sol,data_hic->npix*8,oscan);
       // write_file("/home/oceanoptics/debug_file/t_sen",data_hic->t_sen,data_hic->npix*8,oscan);
        //HY1C_out("%d",oscan);
        if ((oscan % 50) == 0)
            HY1C_out("Processing scan #%6d (%d of %d) after %6.0f seconds\n",
        iscan,iscan-sscan+1,escan-sscan+1,
                now()-start_time);

        if (aerec->mode == ON) {
        if (read_aer(&aefile,iscan,aerec) != 0) {
                HY1C_out("-E- %s: Error reading %s at scan %d.\n",
                    argv[0],aefile.name,iscan);
                exit(FATAL_ERROR);
            }
        }

    if (tgrec->mode == ON) {
            if (read_target(&tgfile,iscan,tgrec) != 0) {
                HY1C_out("-E- %s: Error reading %s at scan %d.\n",
                    argv[0],tgfile.name,iscan);
                exit(FATAL_ERROR);
            }
        }

        /*                                                              */
    /* Convert the L1B radiances to L2                              */
    /*                                                              */
    int tmp_hic_npix=data_hic->npix;
        convl12( data_hic, l2rec, 0, tmp_hic_npix-1, input, aerec );
        l2rec->nbands = 8;
        l2rec->nbandsir = 2;

        if (input->mode != FORWARD) {

        /*                                                          */
        /* Recalibration mode. Read target nLw's for this scan and  */
        /* copy into L2 record.  Then reconstruct L1 radiances      */
        /* using the target nLw's and the components of the         */
        /* previous atmospheric correction.                         */
        /*                                                          */
            convl21( l2rec, tgrec, 0, l1rec->npix-1, input, l1rec->Lt, NULL);

        /*                                                          */
        /* Write the new L1B record to output file.                 */
        /*                                                          */
            if (writel1( &ofile[0], oscan, l1rec) != 0) {
                HY1C_out("-E- %s: error writing to %s\n",
                    argv[0],ofile[0].name);
                exit(FATAL_ERROR);
            }

        } else {

        /*                                                          */
        /* Forward mode. Write output record to file(s).            */
        /*                                                          */
            for (i=0; i<num_ofiles; i++)
          //                if (writel2_hdf( &ofile[i], oscan, l2rec) != 0) {
                if (writel2( &ofile[i], oscan, l2rec) != 0) {
                    HY1C_out("-E- %s: error writing to %s\n",
                        argv[0],ofile[i].name);
                    exit(FATAL_ERROR);
                }

        }

    }

    HY1C_out("\nEnd MSl12 processing at %s\n", ydhmsf(now(),'L'));
    HY1C_out("Processing Rate = %f scans/sec\n\n",
        ofile[0].nscan/(now()-start_time));


    /*                                                                  */
    /* Write SeaWifs-specific data if appropriate                       */
    /*                                                                  */
    if (l1file.sensorID == SEAWIFS &&
        (l1file.format == FMT_SEAWIFSL1A || l1file.format == FMT_L1HDF) &&
        (ofile[0].format == FMT_L2HDF || ofile[0].format == FMT_L1HDF ||
     ofile[0].format == FMT_L2NCDF)) {
        HY1C_out("Writing SeaWiFS-specific meta-data\n");
        for (i=0; i<num_ofiles; i++)
            l2_seawifs(&l1file, &ofile[i]);
    }

    /*                                                                  */
    /* Close all files                                                  */
    /*                                                                  */
    closel1(&l1file);

    if (input->mode != FORWARD) {
        closel1(&ofile[0]);
        if (input->mode != INVERSE_ZERO)
            close_target(&tgfile);
    } else
        for (i=0; i<num_ofiles; i++)
            closel2(&ofile[i]);

    //free_l1(l1rec);
    //free_l2(l2rec);
    free_l1q();

    // free structures
    free(l1rec);
    free(l2rec);
    free(tgrec);
    free(aerec);
    free(input);

    HY1C_out("\nProcessing Completed\n");

    return(SUCCESS);
}


